home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / twin16.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  17KB  |  635 lines

  1. /* vidhrdw/twin16.c
  2.  
  3.     Known Issues:
  4.         sprite-tilemap priority isn't right (see Devil's World intro)
  5.         some rogue sprites in Devil's World
  6.  
  7.     to do:
  8.         8BPP support
  9.         assorted optimizations
  10. */
  11.  
  12. #define USE_16BIT
  13.  
  14. #include "vidhrdw/generic.h"
  15.  
  16. extern UINT16 twin16_custom_vidhrdw;
  17. extern UINT16 *twin16_gfx_rom;
  18. extern unsigned char *twin16_fixram;
  19. extern unsigned char *twin16_sprite_gfx_ram;
  20. extern unsigned char *twin16_tile_gfx_ram;
  21. extern void twin16_gfx_decode( void );
  22. extern int twin16_spriteram_process_enable( void );
  23.  
  24. static int need_process_spriteram;
  25. static UINT16 gfx_bank;
  26. static UINT16 scrollx[3], scrolly[3];
  27. static UINT16 video_register;
  28.  
  29. enum {
  30.     TWIN16_SCREEN_FLIPY        = 0x01,    /* ? breaks devils world text layer */
  31.     TWIN16_SCREEN_FLIPX        = 0x02,    /* confirmed: Hard Puncher Intro */
  32.     TWIN16_UNKNOWN1            = 0x04,    /* ?Hard Puncher uses this */
  33.     TWIN16_PLANE_ORDER        = 0x08,    /* confirmed: Devil Worlds */
  34.     TWIN16_TILE_FLIPY        = 0x20    /* confirmed? Vulcan Venture */
  35. };
  36.  
  37. int twin16_vh_start( void ){
  38.     return 0;
  39. }
  40.  
  41. void twin16_vh_stop( void ){
  42. }
  43.  
  44. /******************************************************************************************/
  45.  
  46. WRITE_HANDLER( fround_gfx_bank_w ){
  47.     gfx_bank = COMBINE_WORD(gfx_bank,data);
  48. }
  49.  
  50. WRITE_HANDLER( twin16_video_register_w ){
  51.     switch( offset ){
  52.         case 0x0: COMBINE_WORD_MEM( &video_register, data ); break;
  53.         case 0x2: COMBINE_WORD_MEM( &scrollx[0], data ); break;
  54.         case 0x4: COMBINE_WORD_MEM( &scrolly[0], data ); break;
  55.         case 0x6: COMBINE_WORD_MEM( &scrollx[1], data ); break;
  56.         case 0x8: COMBINE_WORD_MEM( &scrolly[1], data ); break;
  57.         case 0xa: COMBINE_WORD_MEM( &scrollx[2], data ); break;
  58.         case 0xc: COMBINE_WORD_MEM( &scrolly[2], data ); break;
  59.  
  60.         case 0xe:
  61.         logerror("unknown video_register write:%d", data );
  62.         break;
  63.     }
  64. }
  65.  
  66. /******************************************************************************************/
  67.  
  68. static void draw_text( struct osd_bitmap *bitmap ){
  69.     const struct rectangle *clip = &Machine->drv->visible_area;
  70.     const UINT16 *source = (UINT16 *)twin16_fixram;
  71.     int i;
  72.  
  73.     int tile_flipx = 0;
  74.     int tile_flipy = 0;
  75.     //if( video_register&TWIN16_SCREEN_FLIPY ) tile_flipy = !tile_flipy;
  76.     if( video_register&TWIN16_SCREEN_FLIPX ) tile_flipx = !tile_flipx;
  77.  
  78.     for( i=0; i<64*64; i++ ){
  79.         int code = source[i];
  80.  
  81.         int sx = (i%64)*8;
  82.         int sy = (i/64)*8;
  83.  
  84.         if( video_register&TWIN16_SCREEN_FLIPY ) sy = 256-8 - sy;
  85.         if( video_register&TWIN16_SCREEN_FLIPX ) sx = 320-8 - sx;
  86.  
  87.         drawgfx( bitmap, Machine->gfx[0],
  88.             code&0x1ff, /* tile number */
  89.             (code>>9)&0xf, /* color */
  90.             tile_flipx,tile_flipy,
  91.             sx,sy,
  92.             clip,TRANSPARENCY_PEN,0);
  93.     }
  94. }
  95.  
  96. /******************************************************************************************/
  97.  
  98. static void draw_sprite( /* slow slow slow, but it's ok for now */
  99.     struct osd_bitmap *bitmap,
  100.     const UINT16 *pen_data,
  101.     const UINT16 *pal_data,
  102.     int xpos, int ypos,
  103.     int width, int height,
  104.     int flipx, int flipy ){
  105.  
  106.     int x,y;
  107.     if( xpos>=320 ) xpos -= 512;
  108.     if( ypos>=256 ) ypos -= 512;
  109.  
  110.     if( xpos+width>=0 && xpos<320 && ypos+height>16 && ypos<256-16 )
  111.     {
  112.         if (bitmap->depth == 16)
  113.         {
  114.             for( y=0; y<height; y++ )
  115.             {
  116.                 int sy = (flipy)?(ypos+height-1-y):(ypos+y);
  117.                 if( sy>=16 && sy<256-16 )
  118.                 {
  119.                     UINT16 *dest = (UINT16 *)bitmap->line[sy];
  120.                     for( x=0; x<width; x++ )
  121.                     {
  122.                         int sx = (flipx)?(xpos+width-1-x):(xpos+x);
  123.                         if( sx>=0 && sx<320 )
  124.                         {
  125.                             UINT16 pen = pen_data[x/4];
  126.                             switch( x%4 )
  127.                             {
  128.                             case 0: pen = pen>>12; break;
  129.                             case 1: pen = (pen>>8)&0xf; break;
  130.                             case 2: pen = (pen>>4)&0xf; break;
  131.                             case 3: pen = pen&0xf; break;
  132.                             }
  133.                             if( pen ) dest[sx] = pal_data[pen];
  134.                         }
  135.                     }
  136.                 }
  137.                 pen_data += width/4;
  138.             }
  139.         }
  140.         else
  141.         {
  142.             for( y=0; y<height; y++ )
  143.             {
  144.                 int sy = (flipy)?(ypos+height-1-y):(ypos+y);
  145.                 if( sy>=16 && sy<256-16 )
  146.                 {
  147.                     UINT8 *dest = (UINT8 *)bitmap->line[sy];
  148.                     for( x=0; x<width; x++ )
  149.                     {
  150.                         int sx = (flipx)?(xpos+width-1-x):(xpos+x);
  151.                         if( sx>=0 && sx<320 )
  152.                         {
  153.                             UINT16 pen = pen_data[x/4];
  154.                             switch( x%4 )
  155.                             {
  156.                             case 0: pen = pen>>12; break;
  157.                             case 1: pen = (pen>>8)&0xf; break;
  158.                             case 2: pen = (pen>>4)&0xf; break;
  159.                             case 3: pen = pen&0xf; break;
  160.                             }
  161.                             if( pen ) dest[sx] = pal_data[pen];
  162.                         }
  163.                     }
  164.                 }
  165.                 pen_data += width/4;
  166.             }
  167.         }
  168.     }
  169. }
  170.  
  171. void twin16_spriteram_process( void ){
  172.     UINT16 dx = scrollx[0];
  173.     UINT16 dy = scrolly[0];
  174.  
  175.     const UINT16 *source = (const UINT16 *)&spriteram[0x0000];
  176.     const UINT16 *finish = (const UINT16 *)&spriteram[0x3000];
  177.  
  178.     memset( &spriteram[0x3000], 0, 0x800 );
  179.     while( source<finish ){
  180.         UINT16 priority = source[0];
  181.         if( priority & 0x8000 ){
  182.             UINT16 *dest = (UINT16 *)&spriteram[0x3000 + 8*(priority&0xff)];
  183.  
  184.             INT32 xpos = (0x10000*source[4])|source[5];
  185.             INT32 ypos = (0x10000*source[6])|source[7];
  186.  
  187.             UINT16 attributes = source[2]&0x03ff; /* scale,size,color */
  188.             if( priority & 0x0200 ) attributes |= 0x4000;
  189.             attributes |= 0x8000;
  190.  
  191.             dest[0] = source[3]; /* gfx data */
  192.             dest[1] = ((xpos>>8) - dx)&0xffff;
  193.             dest[2] = ((ypos>>8) - dy)&0xffff;
  194.             dest[3] = attributes;
  195.         }
  196.         source += 0x50/2;
  197.     }
  198.     need_process_spriteram = 0;
  199. }
  200.  
  201. /*
  202.  * Sprite Format
  203.  * ----------------------------------
  204.  *
  205.  * Word | Bit(s)           | Use
  206.  * -----+-fedcba9876543210-+----------------
  207.  *   0  | --xxxxxxxxxxxxxx | code
  208.  * -----+------------------+
  209.  *   1  | -------xxxxxxxxx | ypos
  210.  * -----+------------------+
  211.  *   2  | -------xxxxxxxxx | xpos
  212.  * -----+------------------+
  213.  *   3  | x--------------- | enble
  214.  *   3  | -x-------------- | priority?
  215.  *   3  | ------x--------- | yflip?
  216.  *   3  | -------x-------- | xflip
  217.  *   3  | --------xx------ | height
  218.  *   3  | ----------xx---- | width
  219.  *   3  | ------------xxxx | color
  220.  */
  221.  
  222. static void draw_sprites( struct osd_bitmap *bitmap, int pri ){
  223.     int count = 0;
  224.     const UINT16 *source = 0x1800+(UINT16 *)spriteram;
  225.     const UINT16 *finish = source + 0x800;
  226.     pri = pri?0x4000:0x0000;
  227.  
  228.     while( source<finish ){
  229.         UINT16 attributes = source[3];
  230.         UINT16 code = source[0];
  231.  
  232.         if( code!=0xffff && (attributes&0x8000) && (attributes&0x4000)==pri ){
  233.             int xpos = (INT16)source[1];
  234.             int ypos = (INT16)source[2];
  235.  
  236.             const UINT16 *pal_data = Machine->pens+((attributes&0xf)+0x10)*16;
  237.             int height    = 16<<((attributes>>6)&0x3);
  238.             int width    = 16<<((attributes>>4)&0x3);
  239.             const UINT16 *pen_data = 0;
  240.             int flipy = attributes&0x0200;
  241.             int flipx = attributes&0x0100;
  242.  
  243.             if( twin16_custom_vidhrdw ){
  244.                 pen_data = twin16_gfx_rom + 0x80000;
  245.             }
  246.             else {
  247.                 switch( (code>>12)&0x3 ){ /* bank select */
  248.                     case 0:
  249.                     pen_data = twin16_gfx_rom;
  250.                     break;
  251.  
  252.                     case 1:
  253.                     pen_data = twin16_gfx_rom + 0x40000;
  254.                     break;
  255.  
  256.                     case 2:
  257.                     pen_data = twin16_gfx_rom + 0x80000;
  258.                     if( code&0x4000 ) pen_data += 0x40000;
  259.                     break;
  260.  
  261.                     case 3:
  262.                     pen_data = (UINT16 *)twin16_sprite_gfx_ram;
  263.                     break;
  264.                 }
  265.                 code &= 0xfff;
  266.             }
  267.             pen_data += code*0x40;
  268.  
  269.             if( video_register&TWIN16_SCREEN_FLIPY ){
  270.                 ypos = 256-ypos-height;
  271.                 flipy = !flipy;
  272.             }
  273.             if( video_register&TWIN16_SCREEN_FLIPX ){
  274.                 xpos = 320-xpos-width;
  275.                 flipx = !flipx;
  276.             }
  277.  
  278.             //if( sprite_which==count || !keyboard_pressed( KEYCODE_B ) )
  279.             draw_sprite( bitmap, pen_data, pal_data, xpos, ypos, width, height, flipx, flipy );
  280.         }
  281.             count++;
  282.         source += 4;
  283.     }
  284. }
  285.  
  286. static void show_video_register( struct osd_bitmap *bitmap ){
  287. #if 0
  288.     int n;
  289.     for( n=0; n<4; n++ ){
  290.         drawgfx( bitmap, Machine->uifont,
  291.             "0123456789abcdef"[(video_register>>(12-4*n))&0xf],
  292.             0,
  293.             0,0,
  294.             n*6+8,16,
  295.             0,TRANSPARENCY_NONE,0);
  296.     }
  297. #endif
  298. }
  299.  
  300. static void draw_layer( struct osd_bitmap *bitmap, int opaque ){
  301.     const UINT16 *gfx_base;
  302.     const UINT16 *source = (UINT16 *)videoram;
  303.     int i, y1, y2, yd;
  304.     int bank_table[4];
  305.     int dx, dy, palette;
  306.     int tile_flipx = 0; // video_register&TWIN16_TILE_FLIPX;
  307.     int tile_flipy = video_register&TWIN16_TILE_FLIPY;
  308.  
  309.     if( ((video_register&TWIN16_PLANE_ORDER)?1:0) != opaque ){
  310.         source += 0x1000;
  311.         dx = scrollx[2];
  312.         dy = scrolly[2];
  313.         palette = 1;
  314.     }
  315.     else {
  316.         source += 0x0000;
  317.         dx = scrollx[1];
  318.         dy = scrolly[1];
  319.         palette = 0;
  320.     }
  321.  
  322.     if( twin16_custom_vidhrdw ){
  323.         gfx_base = twin16_gfx_rom;
  324.         bank_table[3] = (gfx_bank>>(4*3))&0xf;
  325.         bank_table[2] = (gfx_bank>>(4*2))&0xf;
  326.         bank_table[1] = (gfx_bank>>(4*1))&0xf;
  327.         bank_table[0] = (gfx_bank>>(4*0))&0xf;
  328.     }
  329.     else {
  330.         gfx_base = (UINT16 *)twin16_tile_gfx_ram;
  331.         bank_table[0] = 0;
  332.         bank_table[1] = 1;
  333.         bank_table[2] = 2;
  334.         bank_table[3] = 3;
  335.     }
  336.  
  337.     if( video_register&TWIN16_SCREEN_FLIPX ){
  338.         dx = 256-dx-64;
  339.         tile_flipx = !tile_flipx;
  340.     }
  341.  
  342.     if( video_register&TWIN16_SCREEN_FLIPY ){
  343.         dy = 256-dy;
  344.         tile_flipy = !tile_flipy;
  345.     }
  346.  
  347.     if( tile_flipy ){
  348.         y1 = 7; y2 = -1; yd = -1;
  349.     }
  350.     else {
  351.         y1 = 0; y2 = 8; yd = 1;
  352.     }
  353.  
  354.     for( i=0; i<64*64; i++ ){
  355.         int sx = (i%64)*8;
  356.         int sy = (i/64)*8;
  357.         int xpos,ypos;
  358.  
  359.         if( video_register&TWIN16_SCREEN_FLIPX ) sx = 63*8 - sx;
  360.         if( video_register&TWIN16_SCREEN_FLIPY ) sy = 63*8 - sy;
  361.  
  362.         xpos = (sx-dx)&0x1ff;
  363.         ypos = (sy-dy)&0x1ff;
  364.         if( xpos>=320 ) xpos -= 512;
  365.         if( ypos>=256 ) ypos -= 512;
  366.  
  367.         if(  xpos>-8 && ypos>8 && xpos<320 && ypos<256-16 ){
  368.             int code = source[i];
  369.             /*
  370.                 xxx-------------    color
  371.                 ---xx-----------    tile bank
  372.                 -----xxxxxxxxxxx    tile number
  373.             */
  374.             const UINT16 *gfx_data = gfx_base + (code&0x7ff)*16 + bank_table[(code>>11)&0x3]*0x8000;
  375.             int color = (code>>13);
  376.             UINT16 *pal_data = Machine->pens + 16*(0x20+color+8*palette);
  377.  
  378.             {
  379.                 int y;
  380.                 UINT16 data;
  381.                 int pen;
  382.  
  383.                 if( tile_flipx )
  384.                 {
  385.                     if( opaque )
  386.                     {
  387.                         if (bitmap->depth == 16)
  388.                         {
  389.                             for( y=y1; y!=y2; y+=yd )
  390.                             {
  391.                                 UINT16 *dest = ((UINT16 *)bitmap->line[ypos+y])+xpos;
  392.                                 data = *gfx_data++;
  393.                                 dest[7] = pal_data[(data>>4*3)&0xf];
  394.                                 dest[6] = pal_data[(data>>4*2)&0xf];
  395.                                 dest[5] = pal_data[(data>>4*1)&0xf];
  396.                                 dest[4] = pal_data[(data>>4*0)&0xf];
  397.                                 data = *gfx_data++;
  398.                                 dest[3] = pal_data[(data>>4*3)&0xf];
  399.                                 dest[2] = pal_data[(data>>4*2)&0xf];
  400.                                 dest[1] = pal_data[(data>>4*1)&0xf];
  401.                                 dest[0] = pal_data[(data>>4*0)&0xf];
  402.                             }
  403.                         }
  404.                         else
  405.                         {
  406.                             for( y=y1; y!=y2; y+=yd )
  407.                             {
  408.                                 UINT8 *dest = ((UINT8 *)bitmap->line[ypos+y])+xpos;
  409.                                 data = *gfx_data++;
  410.                                 dest[7] = pal_data[(data>>4*3)&0xf];
  411.                                 dest[6] = pal_data[(data>>4*2)&0xf];
  412.                                 dest[5] = pal_data[(data>>4*1)&0xf];
  413.                                 dest[4] = pal_data[(data>>4*0)&0xf];
  414.                                 data = *gfx_data++;
  415.                                 dest[3] = pal_data[(data>>4*3)&0xf];
  416.                                 dest[2] = pal_data[(data>>4*2)&0xf];
  417.                                 dest[1] = pal_data[(data>>4*1)&0xf];
  418.                                 dest[0] = pal_data[(data>>4*0)&0xf];
  419.                             }
  420.                         }
  421.                     }
  422.                     else
  423.                     {
  424.                         if (bitmap->depth == 16)
  425.                         {
  426.                             for( y=y1; y!=y2; y+=yd )
  427.                             {
  428.                                 UINT8 *dest = ((UINT8 *)bitmap->line[ypos+y])+xpos;
  429.                                 data = *gfx_data++;
  430.                                 if( data )
  431.                                 {
  432.                                     pen = (data>>4*3)&0xf; if( pen ) dest[7] = pal_data[pen];
  433.                                     pen = (data>>4*2)&0xf; if( pen ) dest[6] = pal_data[pen];
  434.                                     pen = (data>>4*1)&0xf; if( pen ) dest[5] = pal_data[pen];
  435.                                     pen = (data>>4*0)&0xf; if( pen ) dest[4] = pal_data[pen];
  436.                                 }
  437.                                 data = *gfx_data++;
  438.                                 if( data )
  439.                                 {
  440.                                     pen = (data>>4*3)&0xf; if( pen ) dest[3] = pal_data[pen];
  441.                                     pen = (data>>4*2)&0xf; if( pen ) dest[2] = pal_data[pen];
  442.                                     pen = (data>>4*1)&0xf; if( pen ) dest[1] = pal_data[pen];
  443.                                     pen = (data>>4*0)&0xf; if( pen ) dest[0] = pal_data[pen];
  444.                                 }
  445.                             }
  446.                         }
  447.                         else
  448.                         {
  449.                             for( y=y1; y!=y2; y+=yd )
  450.                             {
  451.                                 UINT16 *dest = ((UINT16 *)bitmap->line[ypos+y])+xpos;
  452.                                 data = *gfx_data++;
  453.                                 if( data )
  454.                                 {
  455.                                     pen = (data>>4*3)&0xf; if( pen ) dest[7] = pal_data[pen];
  456.                                     pen = (data>>4*2)&0xf; if( pen ) dest[6] = pal_data[pen];
  457.                                     pen = (data>>4*1)&0xf; if( pen ) dest[5] = pal_data[pen];
  458.                                     pen = (data>>4*0)&0xf; if( pen ) dest[4] = pal_data[pen];
  459.                                 }
  460.                                 data = *gfx_data++;
  461.                                 if( data )
  462.                                 {
  463.                                     pen = (data>>4*3)&0xf; if( pen ) dest[3] = pal_data[pen];
  464.                                     pen = (data>>4*2)&0xf; if( pen ) dest[2] = pal_data[pen];
  465.                                     pen = (data>>4*1)&0xf; if( pen ) dest[1] = pal_data[pen];
  466.                                     pen = (data>>4*0)&0xf; if( pen ) dest[0] = pal_data[pen];
  467.                                 }
  468.                             }
  469.                         }
  470.                     }
  471.                 }
  472.                 else
  473.                 {
  474.                     if( opaque )
  475.                     {
  476.                         if (bitmap->depth == 16)
  477.                         {
  478.                             for( y=y1; y!=y2; y+=yd )
  479.                             {
  480.                                 UINT16 *dest = ((UINT16 *)bitmap->line[ypos+y])+xpos;
  481.                                 data = *gfx_data++;
  482.                                 *dest++ = pal_data[(data>>4*3)&0xf];
  483.                                 *dest++ = pal_data[(data>>4*2)&0xf];
  484.                                 *dest++ = pal_data[(data>>4*1)&0xf];
  485.                                 *dest++ = pal_data[(data>>4*0)&0xf];
  486.                                 data = *gfx_data++;
  487.                                 *dest++ = pal_data[(data>>4*3)&0xf];
  488.                                 *dest++ = pal_data[(data>>4*2)&0xf];
  489.                                 *dest++ = pal_data[(data>>4*1)&0xf];
  490.                                 *dest++ = pal_data[(data>>4*0)&0xf];
  491.                             }
  492.                         }
  493.                         else
  494.                         {
  495.                             for( y=y1; y!=y2; y+=yd )
  496.                             {
  497.                                 UINT8 *dest = ((UINT8 *)bitmap->line[ypos+y])+xpos;
  498.                                 data = *gfx_data++;
  499.                                 *dest++ = pal_data[(data>>4*3)&0xf];
  500.                                 *dest++ = pal_data[(data>>4*2)&0xf];
  501.                                 *dest++ = pal_data[(data>>4*1)&0xf];
  502.                                 *dest++ = pal_data[(data>>4*0)&0xf];
  503.                                 data = *gfx_data++;
  504.                                 *dest++ = pal_data[(data>>4*3)&0xf];
  505.                                 *dest++ = pal_data[(data>>4*2)&0xf];
  506.                                 *dest++ = pal_data[(data>>4*1)&0xf];
  507.                                 *dest++ = pal_data[(data>>4*0)&0xf];
  508.                             }
  509.                         }
  510.                     }
  511.                     else
  512.                     {
  513.                         if (bitmap->depth == 16)
  514.                         {
  515.                             for( y=y1; y!=y2; y+=yd )
  516.                             {
  517.                                 UINT16 *dest = ((UINT16 *)bitmap->line[ypos+y])+xpos;
  518.                                 data = *gfx_data++;
  519.                                 if( data )
  520.                                 {
  521.                                     pen = (data>>4*3)&0xf; if( pen ) dest[0] = pal_data[pen];
  522.                                     pen = (data>>4*2)&0xf; if( pen ) dest[1] = pal_data[pen];
  523.                                     pen = (data>>4*1)&0xf; if( pen ) dest[2] = pal_data[pen];
  524.                                     pen = (data>>4*0)&0xf; if( pen ) dest[3] = pal_data[pen];
  525.                                 }
  526.                                 data = *gfx_data++;
  527.                                 if( data )
  528.                                 {
  529.                                     pen = (data>>4*3)&0xf; if( pen ) dest[4] = pal_data[pen];
  530.                                     pen = (data>>4*2)&0xf; if( pen ) dest[5] = pal_data[pen];
  531.                                     pen = (data>>4*1)&0xf; if( pen ) dest[6] = pal_data[pen];
  532.                                     pen = (data>>4*0)&0xf; if( pen ) dest[7] = pal_data[pen];
  533.                                 }
  534.                             }
  535.                         }
  536.                         else
  537.                         {
  538.                             for( y=y1; y!=y2; y+=yd )
  539.                             {
  540.                                 UINT8 *dest = ((UINT8 *)bitmap->line[ypos+y])+xpos;
  541.                                 data = *gfx_data++;
  542.                                 if( data )
  543.                                 {
  544.                                     pen = (data>>4*3)&0xf; if( pen ) dest[0] = pal_data[pen];
  545.                                     pen = (data>>4*2)&0xf; if( pen ) dest[1] = pal_data[pen];
  546.                                     pen = (data>>4*1)&0xf; if( pen ) dest[2] = pal_data[pen];
  547.                                     pen = (data>>4*0)&0xf; if( pen ) dest[3] = pal_data[pen];
  548.                                 }
  549.                                 data = *gfx_data++;
  550.                                 if( data )
  551.                                 {
  552.                                     pen = (data>>4*3)&0xf; if( pen ) dest[4] = pal_data[pen];
  553.                                     pen = (data>>4*2)&0xf; if( pen ) dest[5] = pal_data[pen];
  554.                                     pen = (data>>4*1)&0xf; if( pen ) dest[6] = pal_data[pen];
  555.                                     pen = (data>>4*0)&0xf; if( pen ) dest[7] = pal_data[pen];
  556.                                 }
  557.                             }
  558.                         }
  559.                     }
  560.                 }
  561.             }
  562.         }
  563.     }
  564. }
  565.  
  566. static void mark_used_colors( void ){
  567.     const UINT16 *source, *finish;
  568.     unsigned char used[0x40], *used_ptr;
  569.     memset( used, 0, 0x40 );
  570.  
  571.     /* text layer */
  572.     used_ptr = &used[0x00];
  573.     source = (UINT16 *)twin16_fixram;
  574.     finish = source + 0x1000;
  575.     while( source<finish ){
  576.         int code = *source++;
  577.         used_ptr[(code>>9)&0xf] = 1;
  578.     }
  579.  
  580.     /* sprites */
  581.     used_ptr = &used[0x10];
  582.     source = 0x1800+(UINT16 *)spriteram;
  583.     finish = source + 0x800;
  584.     while( source<finish ){
  585.         UINT16 attributes = source[3];
  586.         UINT16 code = source[0];
  587.         if( code!=0xffff && (attributes&0x8000) ) used_ptr[attributes&0xf] = 1;
  588.         source++;
  589.     }
  590.  
  591.     /* plane#0 */
  592.     used_ptr = &used[0x20];
  593.     source = (UINT16 *)videoram;
  594.     finish = source+0x1000;
  595.     while( source<finish ){
  596.         int code = *source++;
  597.         used_ptr[code>>13] = 1;
  598.     }
  599.  
  600.     /* plane#1 */
  601.     used_ptr = &used[0x28];
  602.     source = 0x1000+(UINT16 *)videoram;
  603.     finish = source+0x1000;
  604.     while( source<finish ){
  605.         int code = *source++;
  606.         used_ptr[code>>13] = 1;
  607.     }
  608.  
  609.     {
  610.         int i;
  611.         memset( palette_used_colors, PALETTE_COLOR_UNUSED, 0x400 );
  612.         for( i=0; i<0x40; i++ ){
  613.             if( used[i] ){
  614.                 memset( &palette_used_colors[i*16], PALETTE_COLOR_VISIBLE, 0x10 );
  615.             }
  616.         }
  617.     }
  618. }
  619.  
  620. void twin16_vh_screenrefresh( struct osd_bitmap *bitmap, int fullrefresh ){
  621.     if( twin16_spriteram_process_enable() && need_process_spriteram ) twin16_spriteram_process();
  622.     need_process_spriteram = 1;
  623.  
  624.     mark_used_colors();
  625.     palette_recalc();
  626.  
  627.     draw_layer( bitmap,1 );
  628.     draw_sprites( bitmap, 1 );
  629.     draw_layer( bitmap,0 );
  630.     draw_sprites( bitmap, 0 );
  631.     draw_text( bitmap );
  632.  
  633.     show_video_register( bitmap );
  634. }
  635.